//泛型
// 泛型允许我们在定义函数、类或接⼝时，使⽤类型参数来表示未指定的类型，这些参数在具体
// 使⽤时，才被指定具体的类型，泛型能让同⼀段代码适⽤于多种类型，同时仍然保持类型的安
// 全性。
// 举例：如下代码中 <T> 就是泛型，（不⼀定⾮叫 T ），设置泛型后即可在函数中使⽤ T 来表
// 示该类型：

//泛型函数
function logData<T>(data: T) {
    console.log(data)
}
logData<number>(123)
logData<string>("123")
logData<boolean>(false)
// console.log(Date.now())

//泛型可以有多个 
function logData2<T, U>(data: T, data2: U): T | U {
    return Date.now() % 2 ? data : data2
}
logData2<number, boolean>(123, false)
logData2<number, string>(666, '123')

//泛型接⼝ 
interface PersonInerface<T> {
    name: string,
    age: number,
    extraInfo: T
}

type Jobinfo = {
    title: string,
    company: string
}

let p1: PersonInerface<number> = {
    name: '123',
    age: 123,
    extraInfo: 123
}

let p2: PersonInerface<Jobinfo> = {
    name: '123',
    age: 123,
    extraInfo: {
        title: '123',
        company: '123'
    }
}

//泛型类 
class Person11<T> {
    constructor(public name: string, public age: number, public extraInfo: T) {

    }
    public speack() {
        console.log(`我叫${this.name}今年${this.age}岁了`)
        console.log(this.extraInfo)
    }
}
// 测试代码1
const p11 = new Person11<number>('123', 123, 123)
p11.speack()

// interface Jobinfo2 {
//     title: string,
//     company: string
// }

// 测试代码2
const p12 = new Person11<Jobinfo>('123', 123, { title: '123', company: '123' })
p12.speack()


//泛型约束 
interface LengthInterface {
    length: number
}
// 约束规则是：传⼊的类型T必须具有 length 属性
function logPerson<T extends LengthInterface>(data: T): void {
    console.log(data.length)
}
logPerson<string>('hello') 
// 报错：因为number不具备length属性
// logPerson<number>(100)

